#include "include.h"
#include "bsp_led.h"
#include "bsp_rgb_light.h"

#define MAX_GRB_LED 2
#define LED_ON 1
#define LED_OFF 0
#define BREATHE_ON 0
#define BREATHE_OFF 0xFFFF
#define MAX_LIGHT_MODE 5

led_param_t led_info;
u8 rgb_led_buf[7];
u8 active_led_buf[7];
u32 delay_ticks;

u8 random_num;
//led_status_t grow_info;
typedef struct
{
	u8 tick_start;
	u8 tick_cnt;
	u8 fade_start;
	u16 fade_steps;	//渐变过程变量
	u16 color_switch_time;	//过多长时间切换颜色Calm,Aurora,Energy,pulse需要
	u16 fade_offset;
}disp_status_t;
typedef struct
{
	u8 light_mode;
	u16 cur_light_duty;
	u16 next_light_duty;
	u8 time_count;
	u8 fade_step;
	u8 fade_total;
	u8 light_off_flag;
	u8 adjust_dir;
	u8 light_grow_start;
}light_info_t;
light_info_t light_info;

disp_status_t grow_info;
u8 cur_duty_table[7];
u8 next_duty_table[7];
AT(.com_text.rgb.table)
const u8 grow_table_1[7]=
{
	LED_ON,LED_OFF,LED_ON,LED_OFF,LED_ON,LED_OFF,LED_ON
};
AT(.com_text.rgb.table)
const u8 grow_table_2[7]=
{
	LED_OFF,LED_ON,LED_OFF,LED_ON,LED_OFF,LED_ON,LED_OFF
};
AT(.com_text.rgb.table)
const u16 light_duty[MAX_LIGHT_MODE]=
{
	//0xb800,0x9c00,0x6c00//0x2800,0x2500,0x200//0x2b00,0x2500,0x500//0xD000,0xa000,0x10000  //%0,%42,%16
	//0xb800,0x9880,0x85E0,0x5ed0 ////%0,%18,%30,%49
	//0x1700,0x13e0,0x1300,0xc00
	//0x2100,0x1f00,0x1980,0xe80  //v1.01
	0x20b0,0x2400,0x1e80,0x1700,0x1000
};//1%=0x1dc
AT(.com_text.rgb.table)
const u16 light_duty_yellow[MAX_LIGHT_MODE]=
{
	//0xb800,0x9c00,0x6c00//0x2800,0x2500,0x200//0x2b00,0x2500,0x500//0xD000,0xa000,0x10000  //%0,%42,%16
	//0xb800,0x9880,0x85E0,0x5ed0 ////%0,%18,%30,%49
	//0x1700,0x13e0,0x1300,0xc00
	//0x2100,0x1f00,0x1980,0xe80  //v1.01
	//0x20b0,0x2200,0x1d00,0x1780,0xf00
	0x20b0,0x2200,0x1d00,0x1600,0xD80
};//1%=0x1dc

AT(.com_text.rgb.table)
const u16 light_duty_ext[MAX_LIGHT_MODE]=
{
	//0xb800,0x9c00,0x6c00//0x2800,0x2500,0x200//0x2b00,0x2500,0x500//0xD000,0xa000,0x10000  //%0,%42,%16
	//0xb800,0x9880,0x85E0,0x5ed0 ////%0,%18,%30,%49
	//0x1700,0x13e0,0x1300,0xc00
	//0x2100,0x1f00,0x1980,0xe80  //v1.01
	0x20b0,0x2500,0x1f00,0x1800,0x1280
};//1%=0x1dc


AT(.com_text.rgb)
void com_memcpy(void *dst,const void *src,size_t length)
{
	while(length--)
	{
		*(char*)dst=*(char*)src;
		dst=(char*)dst+1;
		src=(char*)src+1;
	}
}
AT(.com_text.rgb)
void com_memset(void *s,int c,size_t n)
{
	const unsigned char uc = c;
	unsigned char *su;
	for(su = s;0 < n;++su,--n)
	*su = uc;
}



AT(.text.led_disp)
void bsp_led_bt_pair_init(void)
{
	led_info.timer_start=1;
	led_info.time_out=1;
	led_info.time_cnt=1;
	LED_SET_ONOFF(LED_1,LED_OFF);
	//com_memset(rgb_led_buf,LED_OFF,MAX_GRB_LED);
	//rgb_led_set();
}
AT(.com_text.led_disp)
void bsp_led_bt_pair(void)
{
	u8 led_status;
	led_info.led_step++;
	if(led_info.led_step>1)
	{
		led_info.led_step=0;
	}
	switch(led_info.led_step)
	{
		case 1:
			led_status=LED_OFF;

			break;
		case 0:
		    led_status=LED_ON;
			break;
		default:
			break;
	}
	LED_SET_ONOFF(LED_1,led_status);
	led_info.time_cnt=0;
	led_info.time_out=10;

}

AT(.text.led_disp)
void bsp_led_bt_reconnect_init(void)
{
	led_info.timer_start=1;
	led_info.time_out=1;
	led_info.time_cnt=1;
	//com_memset(rgb_led_buf,LED_OFF,MAX_GRB_LED);
	//rgb_led_set();
}
AT(.com_text.led_disp)
void bsp_led_bt_reconnect(void)
{
	u8 led_status;
	led_info.led_step++;
	if(led_info.led_step>1)
	{
		led_info.led_step=0;
	}
	switch(led_info.led_step)
	{
		case 1:
		    led_status=LED_ON;
			break;
		case 0:
		    led_status=LED_OFF;
			break;
		default:
			break;
	}
	LED_SET_ONOFF(LED_1,led_status);
	led_info.time_cnt=0;
	led_info.time_out=30;

}
AT(.text.led_disp)
void bsp_led_bt_call_coming_init(void)
{
	led_info.timer_start=1;
	led_info.time_out=1;
	led_info.time_cnt=1;
}
AT(.com_text.led_disp)
void bsp_led_bt_call_coming(void)
{
	u8 led_status;
	led_info.led_step++;
	if(led_info.led_step>1)
	{
		led_info.led_step=0;
	}
	switch(led_info.led_step)
	{
		case 1:
		    led_status=LED_ON;
			break;
		case 0:
		    led_status=LED_OFF;
			break;
		default:
			break;
	}
	LED_SET_ONOFF(LED_1,led_status);
	led_info.time_cnt=0;
	led_info.time_out=4;

}
AT(.text.led_disp)
void bsp_led_bt_call_reject_init(void)
{
	led_info.timer_start=1;
	led_info.time_out=1;
	led_info.time_cnt=1;
}
AT(.com_text.led_disp)
void bsp_led_bt_call_reject(void)
{
	u8 led_status;
	led_info.led_step++;
	if(led_info.led_step>5)
	{
		led_info.led_step=0;
		bsp_set_led_mode(LED_BT_CONNECTED);
		return;
	}
	//printf("led_step:%d\n",led_info.led_step);
	if(led_info.led_step%2==0)
	{
		led_status=LED_ON;
	}
	else
	{
		led_status=LED_OFF;
	}
	LED_SET_ONOFF(LED_1,led_status);
	led_info.time_cnt=0;
	led_info.time_out=20;

}

AT(.text.led_disp)
void bsp_led_bt_pair_fail_init(void)
{
	led_info.timer_start=1;
	led_info.time_out=1;
	led_info.time_cnt=1;
	led_info.led_step=0;
	//com_memset(rgb_led_buf,LED_OFF,MAX_GRB_LED);
	//rgb_led_set();
}
AT(.text.led_disp)
void bsp_led_bt_connected_init(void)
{
	led_info.timer_start=0;
	LED_SET_ONOFF(LED_1,LED_ON);
}
AT(.text.led_disp)
void bsp_led_poweron_init(void)
{
	led_info.timer_start=0;
	LED_SET_ONOFF(LED_1,LED_ON);
}
AT(.text.led_disp)
void bsp_led_poweroff_init(void)
{
	led_info.timer_start=0;
	LED_SET_ONOFF(LED_1,LED_OFF);
}

AT(.com_text.led_disp)
void bsp_led_bt_pair_fail(void)
{
	u8 led_status;
	led_info.led_step++;
	if(led_info.led_step>5)
	{
		led_info.led_step=0;
		bsp_set_led_mode(LED_POWER_OFF);
		return;
	}
	//printf("led_step:%d\n",led_info.led_step);
	if(led_info.led_step%2==0)
	{
		led_status=LED_ON;
	}
	else
	{
		led_status=LED_OFF;
	}
	LED_SET_ONOFF(LED_1,led_status);
	led_info.time_cnt=0;
	led_info.time_out=5;

}

AT(.com_text.led_disp)
void bsp_led_bt_timer(void)
{
	//if(tick_check_expire(delay_ticks,50))
	{
		//delay_ticks = tick_get();
		if(!led_info.timer_start)
		{
			return;
		}
		led_info.time_cnt++;
		if(led_info.time_cnt<led_info.time_out)
		{
			return;
		}
		switch(led_info.led_mode)
		{
			case LED_BT_PAIR:
				bsp_led_bt_pair();
				break;
			case LED_BT_RECONNECT:
			case LED_BT_IDLE:
				bsp_led_bt_reconnect();
				break;
			case LED_BT_PAIR_FAIL:
				bsp_led_bt_pair_fail();
				break;
			case LED_BT_CALL_COMING:
				bsp_led_bt_call_coming();
				break;
			case LED_BT_CALL_REJECT:
				bsp_led_bt_call_reject();
				break;
			default:
				break;
		}

	}
}

AT(.text.led_disp)
void bsp_light_grow_init(void)
{
	led_info.led_step=0;
	grow_info.fade_steps=0;
	grow_info.color_switch_time=100;//500ms 周期，20 ms timer
	if(sys_cb.pwm_mode==2)
	{
		grow_info.fade_offset=(light_duty_ext[0]-light_duty_ext[MAX_LIGHT_MODE-1])/grow_info.color_switch_time;
	}
	else if(sys_cb.pwm_mode==1)
	{
		grow_info.fade_offset=(light_duty_yellow[0]-light_duty_yellow[MAX_LIGHT_MODE-1])/grow_info.color_switch_time;
	}
	else
	{
		grow_info.fade_offset=(light_duty[0]-light_duty[MAX_LIGHT_MODE-1])/grow_info.color_switch_time;
	}

	grow_info.fade_start=1;
	delay_ticks=tick_get();
	printf("fade_offset:%d\n",grow_info.fade_offset);
}
AT(.com_text.led_disp)
u32 get_fade_diff(u16 cur_duty, u16 to_duty, u32 fade_counter, u32 fade_offset)
{
	u32 fade_diff;
	if(cur_duty > to_duty)
	{
		if(cur_duty>(fade_counter*fade_offset))
		{
			fade_diff=cur_duty-(fade_counter*fade_offset);
		}
		else
		{
			fade_diff=to_duty;
		}
	}
	else
	{
		if(to_duty>(fade_counter*fade_offset))
		{
			fade_diff=cur_duty+fade_counter*fade_offset;
		}
		else
		{
			fade_diff=to_duty;
		}

	}

	return fade_diff;
}
/* 颜色渐变模式 glow 模式 = (0~255) */
AT(.com_text.led_disp)
u8 display_glow_mode(disp_status_t* p_disp_status)
{

	u16 set_duty_table;	/* fade 差值 */

	if(p_disp_status->fade_steps > p_disp_status->color_switch_time)
	{
		p_disp_status->fade_steps = 0;
		return 1;
	}
	if(sys_cb.pwm_mode==2)
	{
		set_duty_table = get_fade_diff(
				light_duty_ext[0],
				light_duty_ext[MAX_LIGHT_MODE-1],
				p_disp_status->fade_steps,
				p_disp_status->fade_offset);
	}
	else if(sys_cb.pwm_mode==1)
	{
		set_duty_table = get_fade_diff(
				light_duty_yellow[0],
				light_duty_yellow[MAX_LIGHT_MODE-1],
				p_disp_status->fade_steps,
				p_disp_status->fade_offset);
	}
	else
	{
		set_duty_table = get_fade_diff(
				light_duty[0],
				light_duty[MAX_LIGHT_MODE-1],
				p_disp_status->fade_steps,
				p_disp_status->fade_offset);
	}

		//printf("cur duty:0x%x\n",set_duty_table);
	LED_SET_BREATHE(0, set_duty_table);
	return 0;
}
//AT(.com_text.detstr)
//char step_str[] = "fade_steps:%d->time:%d\n";

AT(.com_text.led_disp)
void bsp_light_grow_timer(void)
{
	//u32 ticks_tmp=0;
	if(!grow_info.fade_start)
	{
		return;
	}
	//if(tick_check_expire(delay_ticks,20))
	{
		//ticks_tmp= tick_get();
		//ticks_tmp=ticks_tmp-delay_ticks;

		grow_info.fade_steps++;
		//printf(step_str,grow_info.fade_steps,ticks_tmp);
		//delay_ticks=tick_get();
		if(display_glow_mode(&grow_info))
		{
			grow_info.fade_start=0;
		}

	}
}
u8 bsp_get_light_mode(void)
{
	return led_info.light_mode;
}
void bsp_set_light_off(void)
{
	led_info.light_mode=1;
	bsp_set_light_mode();
}
void bsp_reset_light_mode(void)
{
	led_info.light_mode=1;
	sys_cb.pwm_mode=0;
	bsp_set_light_mode();
}

u8 bsp_set_pwm_mode(void)
{
	sys_cb.pwm_mode++;
	if(sys_cb.pwm_mode>2)
	{
		sys_cb.pwm_mode=0;
	}
	printf("pwm_mode:%d\n",sys_cb.pwm_mode);
	if(led_info.light_mode==0)
	{
		bsp_set_light_mode();
		return;
	}
	if(sys_cb.pwm_mode==2)
	{
		LED_SET_BREATHE(0, light_duty_ext[led_info.light_mode]);
	}
	else if(sys_cb.pwm_mode==1)
	{
		LED_SET_BREATHE(0, light_duty_yellow[led_info.light_mode]);
	}
	else
	{
		LED_SET_BREATHE(0, light_duty[led_info.light_mode]);
	}
    return 0;
}

u8 bsp_set_light_mode(void)
{
	printf("light mode 00:%d\n",led_info.light_mode);
	if((grow_info.fade_steps!=0)&&(led_info.light_mode==(MAX_LIGHT_MODE-1)))
	{
		return led_info.light_mode;
	}
	printf("light mode AA:%d\n",led_info.light_mode);
	if(led_info.light_mode>0)
	{
		led_info.light_mode--;
	}
	else
	{
		led_info.light_mode=MAX_LIGHT_MODE-1;
		printf("cur sys clk:%d\n",get_cur_sysclk());
		if(get_cur_sysclk()<=SYS_48M)
		{
			set_sys_clk(SYS_CLK_SEL);
		}
	}
	printf("light mode:%d\n",led_info.light_mode);
	if(led_info.light_mode==(MAX_LIGHT_MODE-1))
	{
		bsp_light_grow_init();
	}
	else
	{
		grow_info.fade_start=0;
		if(led_info.light_mode==0)
		{
			LED_SET_BREATHE(0, BREATHE_OFF);
		}
		else
		{
			if(sys_cb.pwm_mode==2)
			{
				LED_SET_BREATHE(0, light_duty_ext[led_info.light_mode]);
			}
			else if(sys_cb.pwm_mode==1)
			{
				LED_SET_BREATHE(0, light_duty_yellow[led_info.light_mode]);
			}
			else
			{
				LED_SET_BREATHE(0, light_duty[led_info.light_mode]);
			}

		}

	}
	return led_info.light_mode;
}

AT(.com_text.led_disp)
void bsp_led_timer(void)
{
	if(led_info.led_mode!=0)
	{
		//bsp_led_Sequence_display();
		bsp_led_bt_timer();
	}
}
AT(.com_text.led_disp)
void bsp_sequence_display_timer(void)
{
	//bsp_led_bt_timer();
	//bsp_light_grow_timer();
}

void bsp_led_mode_init(void)
{
	printf("led mode:%d\n",led_info.led_mode);
	switch(led_info.led_mode)
	{
		case LED_BT_PAIR:
			bsp_led_bt_pair_init();
			break;
		case LED_BT_IDLE:
		case LED_BT_RECONNECT:
			bsp_led_bt_reconnect_init();
			break;
		case LED_BT_PAIR_FAIL:
			bsp_led_bt_pair_fail_init();
			break;
		case LED_POWER_ON:
		case LED_BT_CONNECTED:
			bsp_led_bt_connected_init();
			break;
		case LED_POWER_OFF:
			bsp_led_poweroff_init();
			break;
		case LED_BT_CALL_COMING:
			bsp_led_bt_call_coming_init();
			break;
		case LED_BT_CALL_REJECT:
			bsp_led_bt_call_reject_init();
			break;
		default:
		break;
	}
}
#if 0

u8 test_mode_index=0;

void test_color(void)
{
	printf("test_mode_index:%d\n",test_mode_index);
	//memset(rgb_led_buf,LED_OFF,MAX_GRB_LED);
	//rgb_led_buf[test_mode_index]=LED_ON;
	//LED_SET_ONOFF(test_mode_index,LED_ON);
	com_memset(rgb_led_buf,LED_OFF,MAX_GRB_LED);
	if(test_mode_index>7)
	{
		test_mode_index=0;
	}
	else
	{
		rgb_led_buf[test_mode_index]=LED_ON;
	}
	rgb_led_set();
	test_mode_index++;
	#if 0
	if(test_mode_index>=LED_SEQUENCE_10B)
	{
		test_mode_index=LED_SEQUENCE_1;
	}
	bsp_set_led_mode(test_mode_index);
	#endif
	//rgb_led_set();
}
#endif

void bsp_set_led_mode(u8 led_mode)
{
	if(led_info.led_mode==led_mode)
	{
		return;
	}
	led_info.led_mode=led_mode;
	bsp_led_mode_init();
}

